package nancal.mp.mvc.dev2


import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import nancal.mp.db.mongo.entity.dev.*
import nancal.mp.db.mongo.mor
import nbcp.base.annotation.*
import nbcp.base.annotation.mvc.*
import nbcp.base.comm.*
import nbcp.base.extend.*
import nbcp.base.json.*
import nbcp.base.utils.CodeUtil
import nbcp.base.utils.FileUtil
import nbcp.base.utils.ResourceUtil
import nbcp.base.utils.ZipUtil
import nbcp.mvc.HttpContext
import nbcp.mvc.sys.*
import nbcp.myoql.code.generator.db.mysql.SqlDbEntityGenerator
import nbcp.myoql.code.generator.db.mysql.model.NameCodeInfo
import nbcp.myoql.db.mongo.*
import nbcp.myoql.db.sql.DataSourceScope

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.io.File
import javax.servlet.http.HttpServletRequest

/**
 * Created by CodeGenerator at 2021-04-11 23:42:19
 */
@Api(description = "数据连接", tags = arrayOf("DbConnection"))
@RestController
@RequestMapping("/dev/db-connection")
class DbConnectionAutoController {

    @ApiOperation("列表")
    @PostMapping("/list")
    fun list(
        id: String, //当列表列新一条后，刷新时使用
        name: String,
        @org.springframework.web.bind.annotation.RequestBody query: PagerModel<Any?>,
        request: HttpServletRequest
    ): ListResult<DbConnection> {

        mor.dev.dbConnection.query()
            .apply {
                if (id.HasValue) {
                    this.where { it.id mongoEquals id }
                }
                if (name.HasValue) {
                    this.where { it.name mongoLike name }
                }
            }
            .withPager(query)
            .toListResult()
            .apply {
                return this;
            }
    }

    @ApiOperation("详情")
    @PostMapping("/detail/{id}")
    fun detail(
        @Require id: String,
        request: HttpServletRequest
    ): ApiResult<DbConnection> {
        mor.dev.dbConnection.queryById(id)
            .toEntity()
            .apply {
                if (this == null) {
                    return ApiResult.error<DbConnection>("找不到数据")
                }

                return ApiResult.of(this)
            }
    }

    @ApiOperation("更新")
    @PostMapping("/save")
    fun save(
        @org.springframework.web.bind.annotation.RequestBody entity: DbConnection,
        request: HttpServletRequest
    ): ApiResult<String> {
        //鉴权
        var userId = request.UserId;

        mor.dev.dbConnection.updateWithEntity(entity)

            .run {
                if (entity.id.HasValue) {
                    return@run this.execUpdate()
                } else {
                    return@run this.execInsert()
                }
            }
            .apply {
                if (this == 0) {
                    return ApiResult.error("更新失败")
                }

                return ApiResult.of(entity.id)
            }
    }

    @ApiOperation("更新")
    @PostMapping("/{id}/set-group")
    fun setGroup(
        id: String,
        @org.springframework.web.bind.annotation.RequestBody groupMap: StringMap
    ): JsonResult {
        var conn = mor.dev.dbConnection.queryById(id).toEntity()
            .throwIfNull { "找不到数据库连接信息" }

        var map = conn.groupMap + groupMap.filter { it.value.HasValue }

        mor.dev.dbConnection.updateById(id)
            .set { it.groupMap to map }
            .exec()
        return JsonResult()
    }

    @ApiOperation("删除")
    @PostMapping("/delete/{id}")
    fun delete(
        @Require id: String,
        request: HttpServletRequest
    ): JsonResult {
        //鉴权
        var userId = request.UserId

        var entity = mor.dev.dbConnection.queryById(id).toEntity()
        if (entity == null) {
            return JsonResult.error("找不到数据")
        }

        mor.dev.dbConnection.deleteById(id)
            .exec()
            .apply {
                if (this == 0) {
                    return JsonResult.error("删除失败")
                }
                //实体上配置垃圾箱功能，可物理删除，会自动移到垃圾箱。
                return JsonResult()
            }
    }

    @ApiOperation("markdown")
    @PostMapping("/markdown/{id}")
    fun markdown(
        id: String,
        tables: List<String>,
        groupMap: StringMap,
        uniteGroupName: String
    ): ListResult<NameCodeInfo> {
        var db = mor.dev.dbConnection.queryById(id).toEntity().throwIfNull { "找不到数据库连接" };

        var map = StringMap(db.groupMap + groupMap.filter { it.value.HasValue })

        mor.dev.dbConnection.updateById(id)
            .set { it.groupMap to map }
            .exec()

        usingScope(DataSourceScope(db.getDataSource())) {

            var css = """
<style>
${ResourceUtil.readResourceContentText("markdown.css")}
</style>
"""
            var list = SqlDbEntityGenerator
                .db2Entity()
                .whereTable { tables.size == 0 || it.IsIn(tables) }
                .toMarkdown(uniteGroupName, map)
                .filter { !it.code.startsWith("flyway") }


            return ListResult.of(list).withValue(css);
        }
    }

    @ApiOperation("entities")
    @GetMapping("/entities/download/{id}")
    fun entities(
        id: String,
        packageName: String,
        tables: List<String>
    ) {
        var db = mor.dev.dbConnection.queryById(id).toEntity().throwIfNull { "找不到数据库连接" };

        usingScope(DataSourceScope(db.getDataSource())) {
            var list = SqlDbEntityGenerator
                .db2Entity()
                .whereTable { tables.size == 0 || it.IsIn(tables) }
                .toKotlinCode(packageName)
                .filter { !it.name.startsWith("flyway") }


            list.forEach {
                if (it.name.isEmpty()) {
                    it.name = "empty.kt"
                } else {
                    it.name = it.name + ".kt"
                }
            }

            var file = File(
                FileUtil.resolvePath(
                    System.getProperty("java.io.tmpdir"),
                    CodeUtil.getCode() + ".zip"
                )
            );
            file.parentFile.mkdirs()

            var zipFile = ZipUtil.beginCompress(file);
            list.forEach { idName ->
                var fileName = idName.name + ".kt";
                var text = idName.code
                zipFile.addFile(text.byteInputStream(const.utf8), fileName);
            }

            var response = HttpContext.response;
            response.setDownloadFileName("myoql-entity-code.zip")
            response.outputStream.write(file.readBytes())
            file.delete()
        }
    }

}
